
#include "sample_venc.h"
#include "sample_vdec.h"

extern mpi_mem_map_table_s g_mem_map_table[];


typedef struct __frame_head_t
{
    unsigned char ch;
    unsigned char resolution;
    unsigned char frame_type;    /* 1: i frame 2:p frame 3:audio*/
    unsigned char frame_rate;
    unsigned long frame_size;
    unsigned long sec;
    unsigned long usec;
    int  frame_no;
    char reserve[4];
} frame_head_t;





int sgks_mpi_sample_EnableMjpegVdec(char *filename,int start_mode)
{

    sgks_mpi_vdec_init_Param_s  vdec_Param;
    sgks_mpi_vdec_stop_Param_s  vdec_stop_Param;
   // Printf("[mjpeg] decode filename %s, width %d, height %d\n",filename, width, height);

    int ret = 0;

    vdec_Param.file_info.type					= SGKS_VDEC_TYPE_MJPEG;

    vdec_Param.vdec_buff.buff_ptr_phy			= g_mem_map_table[bsb_buff].phy_addr;
    vdec_Param.vdec_buff.size					= g_mem_map_table[bsb_buff].size;

    //only h264 vdec
    vdec_Param.rescale_sub_num					= 1;
    vdec_Param.rescale_sub[0].stream_id			= 0;
    vdec_Param.rescale_sub[0].width				= 1280;
    vdec_Param.rescale_sub[0].height			= 720;

/*
    ret = sgks_mpi_vdec_Enable(&vdec_Param);
    if (ret < 0)
    {
        return -1;
    }
*/

    /***************dec file***************/
    int fd = -1;
    struct stat fstatbuf;
    int rlen	= 0;
    int size	= 0;
    sgks_mpi_vdec_info_s vdec_info;
    frame_head_t frame_head;
    int num = 0;
    int pos = 0;
	int frame_count=0;

    char *data_buf = (char *)sgks_mpi_Malloc(sizeof(char) * 1024 * 1024);
    if ( data_buf == NULL)
    {
        printf("data_buf == NULL\n");
        return -1;
    }

    fd = open(filename, O_RDWR);
    if (fd <= 0)
    {
        printf("open file err!\n");
        sgks_mpi_Free(data_buf);
        return -1;
    }

    fstat(fd ,&fstatbuf);

    printf("open file ok. name =%s  size = %d\n",filename,fstatbuf.st_size);



	rlen = read(fd, data_buf, sizeof(char) * 1024 * 1024);
	lseek(fd, 0, SEEK_SET);
	
	ret  = Analysis_Mjpeg_Pixel_Info((u8 *)data_buf,rlen,(int *)&vdec_Param.file_info.width,(int *)&vdec_Param.file_info.height);
	if(ret<0)
		return ret;
	memset(data_buf, 0, sizeof(char) * 1024 * 1024);
	Printf("width:%d   height:%d  \n",vdec_Param.file_info.width,vdec_Param.file_info.height);
	if(vdec_Param.file_info.width > MAX_VDEC_WIDTH)
		vdec_Param.file_info.width=MAX_VDEC_WIDTH;
    if(vdec_Param.file_info.height > MAX_VDEC_HEIGHT)
		vdec_Param.file_info.height=MAX_VDEC_HEIGHT;
	ret  = sgks_mpi_vdec_Enable(&vdec_Param);
    if (ret < 0)
    {
        return -1;
    }

	

    while(1)
    {
        if (pos >= fstatbuf.st_size)
        {
            lseek(fd, 0, SEEK_SET);
            pos = 0;
            printf("start begin..............\n");
        }
#if 1
        if (num >= 300)
        {

            printf("dec break\n");
			
            vdec_stop_Param.screen = SGKS_STOP_DEC_CLEAN_SCREEN;
            sgks_mpi_vdec_Disable(&vdec_stop_Param);

            if (start_mode == 1)
            {
                ret = sgks_mpi_sys_DecToEnc(); /*--->ven start*/
                if (ret != SGKS_SUCCESS)
                    return ret;

                Printf("sgks_mpi_sample_venc_start 1\n");
                ret = sgks_mpi_sample_venc_start();
                if (ret != SGKS_SUCCESS)
                    return ret;
                Printf("sgks_mpi_sample_venc_start 2\n");

                sleep(10);

                Printf("sgks_mpi_sample_venc_stop 1\n");
                ret = sgks_mpi_sample_venc_stop();
                if (ret != SGKS_SUCCESS)
                    return ret;
                Printf("sgks_mpi_sample_venc_stop 2\n");
            }

            ret = sgks_mpi_vdec_Enable(&vdec_Param);
            if (ret < 0)
            {
                return -1;
            }

            lseek(fd, 0, SEEK_SET);
            pos = 0;
            num = 0;

            continue;
			
        }
		
#endif


#if 0        //read head
        rlen = read(fd, &frame_head,sizeof(frame_head_t));
        if(rlen != sizeof(frame_head_t))
        {
            printf("error read frame head\n");
            pos = fstatbuf.st_size;
            continue;
        }
        pos += rlen;

        //read frame size
        rlen = read(fd, data_buf, frame_head.frame_size);
        if(rlen != frame_head.frame_size)
        {
            printf("error read the frame\n");
            pos = fstatbuf.st_size;
            continue;
        }
        pos += rlen;
        size=frame_head.frame_size;
#else

		lseek(fd, pos, SEEK_SET);
		rlen=read(fd, data_buf,sizeof(char) * 1024 * 1024);
		ret=find_mjpeg_frame_head((u8 *)data_buf,10,rlen);
		if(ret<0)
		{
			
			pos=0;
			lseek(fd, 0, SEEK_SET);
			size=rlen;
			Printf("sizeof data:%d, frame_count:%d    pos:0x%x  not find the next  mjpeg_frame_head\n",size,frame_count++,pos);
			frame_count=0;
		}
		else
		{
			pos+=ret;
			size=ret;
			Printf("sizeof data:%d, frame_count:%d    pos:0x%x \n",size,frame_count++,pos);
		}
		//Printf("sizeof data: 0x%d\n",size);
        //pos = pos_frame_head;

			
#endif


        printf("send decode: type 0x%x, len: %d -- NUM: %d\n",data_buf[4], size, num++);

        ret = sgks_mpi_vdec_SendData((u8 *)data_buf, size);
        if (ret < 0)
        {
            printf("sgks_mpi_vdec_SendData failed! ret=%d\n", ret);
        }

        // sleep(1);
        usleep(20*1000);
    }



}



int sgks_mpi_sample_EnableH264Vdec(char *filename, int start_mode)
{

    sgks_mpi_vdec_init_Param_s  vdec_Param;
    sgks_mpi_vdec_stop_Param_s  vdec_stop_Param;


    int ret = 0;

    vdec_Param.file_info.type					= SGKS_VDEC_TYPE_H264;

    vdec_Param.vdec_buff.buff_ptr_phy			= g_mem_map_table[bsb_buff].phy_addr;
    vdec_Param.vdec_buff.size					= g_mem_map_table[bsb_buff].size;

    vdec_Param.rescale_sub_num					= 0;
    vdec_Param.rescale_sub[0].stream_id			= 0;
    vdec_Param.rescale_sub[0].width				= 1280;
    vdec_Param.rescale_sub[0].height			= 720;


/*
    ret = sgks_mpi_vdec_Enable(&vdec_Param);
    if (ret < 0)
    {
        return -1;
    }
*/

    /***************dec file***************/
    int fd = -1;
    struct stat fstatbuf;
    int rlen	= 0;
    int size	= 0;
    sgks_mpi_vdec_info_s vdec_info;
    frame_head_t frame_head;
	
    int num = 0;

    int pos = 0;
	int pos_frame_head=0;
	int frame_count=0;


    char *data_buf = (char *)sgks_mpi_Malloc(sizeof(char) * 1024 * 1024);
    if ( data_buf == NULL)
    {
        printf("data_buf == NULL\n");
        return -1;
    }

    fd = open(filename, O_RDWR);
    if (fd <= 0)
    {
        printf("open file err!\n");
        sgks_mpi_Free(data_buf);
        return -1;
    }

    fstat(fd ,&fstatbuf);

    printf("open file ok. name =%s  size = %d\n",filename,fstatbuf.st_size);


	rlen = read(fd, data_buf, sizeof(char) * 1024 * 1024);
	lseek(fd, 0, SEEK_SET);
	
	ret  = Analysis_H264_SPS_Pixel_Info((u8 *)data_buf,rlen,(int *)&vdec_Param.file_info.width,(int *)&vdec_Param.file_info.height);
	if(ret<0)
		return ret;
	memset(data_buf, 0, sizeof(char) * 1024 * 1024);
	Printf("width:%d   height:%d  \n",vdec_Param.file_info.width,vdec_Param.file_info.height);
	if(vdec_Param.file_info.width > MAX_VDEC_WIDTH)
		vdec_Param.file_info.width=MAX_VDEC_WIDTH;
    if(vdec_Param.file_info.height > MAX_VDEC_HEIGHT)
		vdec_Param.file_info.height=MAX_VDEC_HEIGHT;
	ret  = sgks_mpi_vdec_Enable(&vdec_Param);
    if (ret < 0)
    {
        return -1;
    }
	

	
    while(1)
    {
        if (pos >= fstatbuf.st_size)
        {
            lseek(fd, 0, SEEK_SET);
            pos = 0;
            printf("start begin..............\n");
        }
#if 1
        if (num >= 300)
        {

            printf("dec break\n");
            vdec_stop_Param.screen = SGKS_STOP_DEC_CLEAN_SCREEN;
            sgks_mpi_vdec_Disable(&vdec_stop_Param);

            if (start_mode == 1)
            {
                ret = sgks_mpi_sys_DecToEnc(); /*--->ven start*/
                if (ret != SGKS_SUCCESS)
                    return ret;

                Printf("sgks_mpi_sample_venc_start 1\n");
                ret = sgks_mpi_sample_venc_start();
                if (ret != SGKS_SUCCESS)
                    return ret;
                Printf("sgks_mpi_sample_venc_start 2\n");

                sleep(10);

                Printf("sgks_mpi_sample_venc_stop 1\n");
                ret = sgks_mpi_sample_venc_stop();
                if (ret != SGKS_SUCCESS)
                    return ret;
                Printf("sgks_mpi_sample_venc_stop 2\n");
            }

            ret = sgks_mpi_vdec_Enable(&vdec_Param);
            if (ret < 0)
            {
                return -1;
            }

            lseek(fd, 0, SEEK_SET);
            pos = 0;
            num = 0;

            continue;
        }
#endif

#if 0  //the H264 file have frame_head_t?
        //read head
        rlen = read(fd, &frame_head,sizeof(frame_head_t));
        if(rlen != sizeof(frame_head_t))
        {
            printf("error read frame head\n");
            pos = fstatbuf.st_size;
            continue;
        }
        pos += rlen;

        //read frame size
        rlen = read(fd, data_buf, frame_head.frame_size);
        if(rlen != frame_head.frame_size)
        {
            printf("error read the frame\n");
            pos = fstatbuf.st_size;
            continue;
        }
        pos += rlen;
        size=frame_head.frame_size;

#else		
		
		lseek(fd, pos, SEEK_SET);
		rlen=read(fd, data_buf,sizeof(char) * 1024 * 1024);
		ret=find_h264_frame_head((u8 *)data_buf,4,rlen,0,2);
		if(ret<0)
		{
			
			pos=0;
			lseek(fd, 0, SEEK_SET);
			size=rlen;
			Printf("sizeof data:%d, frame_count:%d  not find the next  mjpeg_frame_head\n",size,frame_count++);
			frame_count=0;
		}
		else
		{
			pos+=ret;
			size=ret;
			Printf("sizeof data:%d, frame_count:%d\n",size,frame_count++);
		}
		//Printf("sizeof data: 0x%d\n",size);
        //pos = pos_frame_head;
#endif

        printf("send decode: type 0x%x, len: %d -- NUM: %d\n",data_buf[4], size, num++);

        ret = sgks_mpi_vdec_SendData((u8 *)data_buf, size);
        if (ret < 0)
        {
            printf("sgks_mpi_vdec_SendData failed! ret=%d\n", ret);
        }

        ret = sgks_mpi_vdec_GetDecInfo(&vdec_info);
        if(ret < 0)
        {
            printf("SGKS_Get_VideoDecodeInfo failed!\n");
        }

        printf("get dec info NUM: %d\n", vdec_info.decoded_frames);


        usleep(20*1000);

    }



}


u32 Analysis_Ue_H264_SPS(u8 *pBuff, u32 nLen, u32 *nStartBit)  
{  
    //计算0bit的个数  
    u32 nZeroNum = 0;  
    while (*nStartBit < nLen * 8)  
    {  
        if (pBuff[*nStartBit / 8] & (0x80 >> (*nStartBit % 8))) //&:按位与，%取余  
        {  
            break;  
        }  
        nZeroNum++;  
        (*nStartBit)=(*nStartBit)+1; ;  
    }  
    (*nStartBit)=(*nStartBit)+1; ;  
  
  
    //计算结果  
    u64 dwRet = 0;  
    for (u32 i=0; i<nZeroNum; i++)  
    {  
        dwRet <<= 1;  
        if (pBuff[*nStartBit / 8] & (0x80 >> (*nStartBit % 8)))  
        {  
            dwRet += 1;  
        }  
        (*nStartBit)=(*nStartBit)+1; ;  
    }  
    return (1 << nZeroNum) - 1 + dwRet;  
}  
  
  
int Analysis_Se_H264_SPS(u8 *pBuff, u32 nLen, u32 *nStartBit)  
{  
    int UeVal=Analysis_Ue_H264_SPS(pBuff,nLen,nStartBit);  
    double k=UeVal;  
    int nValue=ceil(k/2);//ceil函数：ceil函数的作用是求不小于给定实数的最小整数。ceil(2)=ceil(1.2)=cei(1.5)=2.00  
    if (UeVal % 2==0)  
        nValue=-nValue;  
    return nValue;  
}  
  
  
u64 Analysis_U_H264_SPS(u32 BitCount,u8 *buf,u32 *nStartBit)  
{  
    u64 dwRet = 0;  
    for (u32 i=0; i<BitCount; i++)  
    {  
        dwRet <<= 1;  
        if (buf[(*nStartBit)/ 8] & (0x80 >> ((*nStartBit) % 8)))  
        {  
            dwRet += 1;  
        }  
        (*nStartBit)=(*nStartBit)+1;  
    }  
    return dwRet;  
}  
  
  
/** 
 * 解码SPS,获取视频图像宽、高和帧率信息 
 * 
 * @param buf SPS数据内容 
 * @param nLen SPS数据的长度 
 * @param width 图像宽度 
 * @param height 图像高度 
 
 * @成功则返回true , 失败则返回false 
 */  
 
int Analysis_H264_SPS_Pixel_Info(u8 * buf,unsigned int nLen,int *width,int *height)  
{  
    u32 StartBit=0;  
    //de_emulation_prevention(buf,&nLen);  
    int ret=0;
	ret=find_h264_frame_head(buf,0,nLen,0x47,1);
	if(ret<0)
		return ret;
	Printf("find_h264_frame_head: 0x%x\n",ret);
	
	StartBit=(ret+4)*8;
	
    int forbidden_zero_bit=Analysis_U_H264_SPS(1,buf,&StartBit);  
    int nal_ref_idc=Analysis_U_H264_SPS(2,buf,&StartBit);  
    int nal_unit_type=Analysis_U_H264_SPS(5,buf,&StartBit);  
    if(nal_unit_type==7)  
    {  
        int profile_idc=Analysis_U_H264_SPS(8,buf,&StartBit);  
        int constraint_set0_flag=Analysis_U_H264_SPS(1,buf,&StartBit);//(buf[1] & 0x80)>>7;  
        int constraint_set1_flag=Analysis_U_H264_SPS(1,buf,&StartBit);//(buf[1] & 0x40)>>6;  
        int constraint_set2_flag=Analysis_U_H264_SPS(1,buf,&StartBit);//(buf[1] & 0x20)>>5;  
        int constraint_set3_flag=Analysis_U_H264_SPS(1,buf,&StartBit);//(buf[1] & 0x10)>>4;  
        int reserved_zero_4bits=Analysis_U_H264_SPS(4,buf,&StartBit);  
        int level_idc=Analysis_U_H264_SPS(8,buf,&StartBit);  
  
        int seq_parameter_set_id=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
  
        if( profile_idc == 100 || profile_idc == 110 ||  
            profile_idc == 122 || profile_idc == 144 )  
        {  
            int chroma_format_idc=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
            if( chroma_format_idc == 3 )  
                int residual_colour_transform_flag=Analysis_U_H264_SPS(1,buf,&StartBit);  
            int bit_depth_luma_minus8=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
            int bit_depth_chroma_minus8=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
            int qpprime_y_zero_transform_bypass_flag=Analysis_U_H264_SPS(1,buf,&StartBit);  
            int seq_scaling_matrix_present_flag=Analysis_U_H264_SPS(1,buf,&StartBit);  
  
            int seq_scaling_list_present_flag[8];  
            if( seq_scaling_matrix_present_flag )  
            {  
                for( int i = 0; i < 8; i++ ) {  
                    seq_scaling_list_present_flag[i]=Analysis_U_H264_SPS(1,buf,&StartBit);  
                }  
            }  
        }  
        int log2_max_frame_num_minus4=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
        int pic_order_cnt_type=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
        if( pic_order_cnt_type == 0 )  
            int log2_max_pic_order_cnt_lsb_minus4=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
        else if( pic_order_cnt_type == 1 )  
        {  
            int delta_pic_order_always_zero_flag=Analysis_U_H264_SPS(1,buf,&StartBit);  
            int offset_for_non_ref_pic=Analysis_Se_H264_SPS(buf,nLen,&StartBit);  
            int offset_for_top_to_bottom_field=Analysis_Se_H264_SPS(buf,nLen,&StartBit);  
            int num_ref_frames_in_pic_order_cnt_cycle=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
  
            int *offset_for_ref_frame=(int *)malloc(sizeof(int)*num_ref_frames_in_pic_order_cnt_cycle);
            for( int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )  
                offset_for_ref_frame[i]=Analysis_Se_H264_SPS(buf,nLen,&StartBit);  
           free(offset_for_ref_frame);
        }  
        int num_ref_frames=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
        int gaps_in_frame_num_value_allowed_flag=Analysis_U_H264_SPS(1,buf,&StartBit);  
        int pic_width_in_mbs_minus1=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
        int pic_height_in_map_units_minus1=Analysis_Ue_H264_SPS(buf,nLen,&StartBit);  
  
        *width=(pic_width_in_mbs_minus1+1)*16;  
        *height=(pic_height_in_map_units_minus1+1)*16;  
		//Printf("width:%d   height:%d  \n",(pic_width_in_mbs_minus1+1)*16,(pic_height_in_map_units_minus1+1)*16);

	
 
        return SGKS_SUCCESS;  
    }  
    else  
        return SGKS_FAIL;  
}  


/****
frame_type = 0 find type_PI(one of 0x47 or 0x41)
frame_type = 1 find P and I (0x47 and 0x41)
****/
int find_h264_frame_head(unsigned       char * src,int start_offset,int len,unsigned char frame_type,unsigned char type_PI)
{
	int i=start_offset;
	len -= 4;
	while(len--)
	{
		if(src[i]==0x00 && src[i+1]==0x00 && src[i+2]==0x00 && src[i+3]==0x01)
		{
			if(type_PI==1 && src[i+4]==frame_type)
				return i;
			else if(type_PI==2 && (src[i+4]==0x47 || src[i+4]==0x41))
				return i;
		}
		i++;
	}
	return SGKS_FAIL;
}

int Analysis_Mjpeg_Pixel_Info(unsigned       char * src,int len,int *width,int *height)
{
	int i=0;
	len -= 8;
	while(len--)
	{
		if(src[i]==0xFF && src[i+1]==0xC0)
		{
			*height=(src[i+5]<<8)+src[i+6];
			*width=(src[i+7]<<8)+src[i+8];
			return SGKS_SUCCESS;
		}
		i++;
	}
	return SGKS_FAIL;
}
/*
for find JFJF-JPEG
*/
int find_mjpeg_frame_head(unsigned       char * src,int start_offset,int len)
{
	int i=start_offset;
	len -= 10;
	while(len--)
	{
		if(src[i]==0xFF && src[i+1]==0xD8 && src[i+2]==0xFF && src[i+3]==0xE0
			&& src[i+6]==0x4A && src[i+7]==0x46 && src[i+8]==0x49 && src[i+9]==0x46 && src[i+10]==0x00)//"jfjf"
		{
			return i;
		}
		i++;
	}
	return SGKS_FAIL;

}



